﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.FxCop.Sdk;

namespace BaseAddIn.Rules
{
    public abstract class BaseRuleFXCop : BaseIntrospectionRule
    {
        private static Dictionary<ClassNode, string> _sources;

        #region Construtores

        static BaseRuleFXCop()
        {
            _sources = new Dictionary<ClassNode, string>();
        }

        public BaseRuleFXCop(string name, string resourceName, System.Reflection.Assembly resourceAssembly)
            : base(name, resourceName, resourceAssembly)
        {

        }

        #endregion

        #region Public Override Methods

        public sealed override void VisitClass(ClassNode classType)
        {
            Method metodo = null;
            string sourceFileName = String.Empty;
            bool encontrouSource = false;

            base.VisitClass(classType);

            if (!_sources.ContainsKey(classType))
            {
                foreach (Member membro in classType.Members)
                {
                    if (membro is Method)
                    {
                        metodo = (Method)membro;

                        foreach (Instruction instruction in metodo.Instructions)
                        {
                            if (!String.IsNullOrEmpty(instruction.SourceContext.FileName))
                            {
                                sourceFileName = instruction.SourceContext.FileName;
                                encontrouSource = true;
                                break;
                            }
                        }
                    }

                    if (encontrouSource)
                        break;
                }

                _sources.Add(classType, sourceFileName);
            }
        }

        #endregion

        #region Public Methods

        public void AddError(Node nodeErro, string resolutionName, params string[] resolutionArguments)
        {
            Member membro = null;
            Problem problema = null;
            ClassNode classe = null;
            Resolution resolucao = this.GetNamedResolution(resolutionName, resolutionArguments);

            try
            {
                if (!String.IsNullOrEmpty(nodeErro.SourceContext.FileName))
                {
                    problema = new Problem(resolucao, nodeErro.SourceContext);
                }
                else
                {
                    if (nodeErro is ClassNode)
                    {
                        classe = (ClassNode)nodeErro;
                    }
                    else if (nodeErro is Member)
                    {
                        membro = (Member)nodeErro;

                        if (membro.DeclaringType is ClassNode)
                        {
                            classe = (ClassNode)membro.DeclaringType;
                        }
                    }

                    if (classe != null)
                    {
                        VisitClass(classe);
                        problema = new Problem(resolucao, _sources[classe], 1);
                    }
                    else
                    {
                        problema = new Problem(resolucao);
                    }
                }
            }
            catch
            {
                problema = new Problem(resolucao);
            }

            base.Problems.Add(problema);
        }

        #endregion
    }
}
